package com.yswee.mallnavi.view.navi;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Picture;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PictureDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.FutureTarget;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.caverock.androidsvg.RenderOptions;
import com.caverock.androidsvg.SVG;
import com.caverock.androidsvg.SVGExternalFileResolver;
import com.caverock.androidsvg.utils.SVGBase;
import com.github.chrisbanes.photoview.OnPhotoTapListener;
import com.github.chrisbanes.photoview.PhotoView;
import com.yswee.framework.data.BaseArrayData;
import com.yswee.framework.data.parser.IParser;
import com.yswee.framework.net.ITaskContext;
import com.yswee.framework.net.http.Callback;
import com.yswee.framework.net.http.Entity;
import com.yswee.framework.utils.FileUtils;
import com.yswee.framework.utils.StringUtils;
import com.yswee.framework.utils.ViewInject;
import com.yswee.framework.widget.MToast;
import com.yswee.framework.widget.loading.LoadingLayout;
import com.yswee.mallnavi.R;
import com.yswee.mallnavi.context.ContextConstant;
import com.yswee.mallnavi.entity.info.CategoryEntity;
import com.yswee.mallnavi.entity.info.MapEntity;
import com.yswee.mallnavi.entity.info.TagEntity;
import com.yswee.mallnavi.model.info.NaviModel;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;


/***
 */
public class ItemView extends LoadingLayout {

    @ViewInject
    private LinearLayout lltags;
    @ViewInject
    private PhotoView imgmap;
    @ViewInject
    private View imgzoomin;
    @ViewInject
    private View imgzoomout;

    private CategoryEntity mDataItem;
    private NaviModel mNaviModel;
    private ArrayList<MapEntity> mMapinfoList;
    private IActionCallback mActionCallback;
    private HashMap<String, WeakReference<Bitmap>> mHashLogo;

    private SVGBase svgBase;

    public void setActionCallback(IActionCallback callback) {
        mActionCallback = callback;
    }

    public void setDataSource(CategoryEntity dataitem) {
        mDataItem = dataitem;
        getTagList();
    }

    @Override
    protected boolean getAutoLoading() {
        return false;
    }

    public ItemView(Context context) {
        super(context);
    }

    public ItemView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected int getLayoutResId() {
        return R.layout.view_info_navi_itemview;
    }

    @Override
    protected void onBindListener() {
        super.onBindListener();
        imgzoomin.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                float scale = imgmap.getScale();
                scale += 1;
                if (scale > imgmap.getMaximumScale()) {
                    scale = imgmap.getMaximumScale();
                }
                imgmap.setScale(scale);
            }
        });
        imgzoomout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                float scale = imgmap.getScale();
                scale -= 1;
                if (scale < imgmap.getMinimumScale()) {
                    scale = imgmap.getMinimumScale();
                }
                imgmap.setScale(scale);
            }
        });
        imgmap.setOnPhotoTapListener(new OnPhotoTapListener() {
            @Override
            public void onPhotoTap(ImageView view, float x, float y) {
                float scale = imgmap.getScale();
                float widthMap = imgmap.getDisplayRect().width() / scale;
                float heightMap = imgmap.getDisplayRect().height() / scale;
                float widthSvg = svgBase.getDocumentViewBox().width();
                float heightSvg = svgBase.getDocumentViewBox().height();
                float scaleSvg = 0;
                if (heightSvg < widthSvg) {
                    scaleSvg = widthSvg / widthMap;
                    float heightSvgRel = heightSvg * widthMap / widthSvg;
                    float heightSub = (heightMap - heightSvgRel) / heightMap / 2;
                    y = y - heightSub;
                } else {
                    scaleSvg = heightSvg / heightMap;
                    float widthSvgRel = widthSvg * heightMap / heightSvg;
                    float widthSub = (widthMap - widthSvgRel) / widthMap / 2;
                    x = x - widthSub;
                }
                x = x * scaleSvg * widthMap;
                y = y * scaleSvg * heightMap;
                if (mMapinfoList != null) {
                    ArrayList<MapEntity> maps = new ArrayList<>();
                    for (MapEntity map : mMapinfoList) {
                        if (map.bizType == 0 && !StringUtils.isEmpty(map.mapId) && !StringUtils.isEmpty(map.bizId)) {
                            if (svgBase.isClickInRegionById(map.mapId, x, y)) {
                                maps.add(map);
                            }
                        }
                    }
                    if (maps.size() > 0) {
                        Collections.sort(maps);
                        // 点中品牌
                        if (mActionCallback != null) {
                            mActionCallback.onBrandClicked(maps.get(maps.size() - 1).bizId);
                        }
                    }
                }
            }
        });
    }

    @Override
    protected void onApplyData() {
        imgmap.setMaximumScale(20);
    }

    @Override
    public void onApplyLoadingData() {
        getTagList();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mHashLogo = new HashMap<>();
        SVGBase.registerExternalFileResolver(new SVGExternalFileResolver() {
            @Override
            public Bitmap resolveImage(String filename) {
                Bitmap bitmap = null;
                if (mHashLogo.containsKey(filename)) {
                    WeakReference<Bitmap> wr = mHashLogo.get(filename);
                    if (wr != null && wr.get() != null) {
                        bitmap = wr.get();
                    }
                }
                return bitmap;
            }
        });
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        SVGBase.deregisterExternalFileResolver();
        if (mHashLogo != null) {
            for (String key : mHashLogo.keySet()) {
                WeakReference<Bitmap> wr = mHashLogo.get(key);
                if (wr != null && wr.get() != null) {
                    try {
                        wr.get().recycle();
                        wr.clear();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            mHashLogo.clear();
            mHashLogo = null;
        }
    }

    private void getTagList() {
        if(mNaviModel == null) {
            ITaskContext context = mContext instanceof ITaskContext ?
                    (ITaskContext) mContext : null;
            mNaviModel = new NaviModel(context);
        }
        gotoLoading();
        mNaviModel.getTagList(mDataItem.id, new Callback<BaseArrayData<TagEntity>>() {
            @Override
            public void onFinish(Entity<BaseArrayData<TagEntity>> entity) {
                IParser<BaseArrayData<TagEntity>> parser = entity.getParser();
                final BaseArrayData<TagEntity> data = entity.getParsedData();
                if(parser.getIsOk() && data != null && data.getArray() != null) {
                    getMapInfo(data.getArray());
                    return;
                }
                String msg = entity.getMessage();
                if(StringUtils.isEmpty(msg)) {
                    msg = getResources().getString(R.string.navi_getdata_fail);
                }
                MToast.showToastMessage(msg);
                gotoError();
            }

            @Override
            public void onError(Entity<BaseArrayData<TagEntity>> entity) {
                gotoError();
                if(entity.getEntityStatus() != Entity.NETINVALID) {
                    MToast.showToastMessage(R.string.navi_getdata_fail);
                }
            }
        });
    }

    private void getMapInfo(ArrayList<TagEntity> tags) {
        if(mNaviModel == null) {
            ITaskContext context = mContext instanceof ITaskContext ?
                    (ITaskContext) mContext : null;
            mNaviModel = new NaviModel(context);
        }
        gotoLoading();
        mNaviModel.getMapInfo(mDataItem.id, new Callback<BaseArrayData<MapEntity>>() {
            @Override
            public void onFinish(Entity<BaseArrayData<MapEntity>> entity) {
                IParser<BaseArrayData<MapEntity>> parser = entity.getParser();
                final BaseArrayData<MapEntity> data = entity.getParsedData();
                if(parser.getIsOk() && data != null && data.getArray() != null) {
                    mMapinfoList = data.getArray();
                    applyDataInfo(tags);
                    gotoSuccessful();
                    return;
                }
                String msg = entity.getMessage();
                if(StringUtils.isEmpty(msg)) {
                    msg = getResources().getString(R.string.navi_getdata_fail);
                }
                MToast.showToastMessage(msg);
                gotoError();
            }

            @Override
            public void onError(Entity<BaseArrayData<MapEntity>> entity) {
                gotoError();
                if(entity.getEntityStatus() != Entity.NETINVALID) {
                    MToast.showToastMessage(R.string.navi_getdata_fail);
                }
            }
        });
    }

    private void applyDataInfo(ArrayList<TagEntity> array) {
        lltags.removeAllViews();
        if(array != null) {
            for(int i = 0; i < array.size(); i++) {
                TagEntity tag = array.get(i);
                RelativeLayout lltag = (RelativeLayout) LayoutInflater.from(mContext).inflate(R.layout.view_info_navi_tag_item, null, false);
                ImageView imgpicture = (ImageView) lltag.getChildAt(0);
                TextView tvtagname = (TextView) lltag.getChildAt(1);
                tvtagname.setText(tag.name);
                lltag.setTag(tag);
                Glide.with(this)
                        .load(tag.iconUrl)
                        .addListener(new RequestListener<Drawable>() {
                            @Override
                            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                                return false;
                            }

                            @Override
                            public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                                imgpicture.setBackgroundResource(R.color.transparent);
                                return false;
                            }
                        })
                        .into(imgpicture);
                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                        (int) mContext.getResources().getDimension(ContextConstant.IS_LANDSCAPE ? R.dimen.dp_35 : R.dimen.dp_50),
                        LinearLayout.LayoutParams.WRAP_CONTENT
                );
//                layoutParams.topMargin = (int) mContext.getResources().getDimension(R.dimen.dp_10);
                layoutParams.rightMargin = (int) mContext.getResources().getDimension(R.dimen.dp_6);
                lltags.addView(lltag, layoutParams);
                if (lltag != null){
                    final int index = i;
                    lltag.setOnClickListener(new OnClickListener() {
                        public void onClick(View v) {
                            TagEntity tagF = (TagEntity) v.getTag();
                            applyMapInfo(tagF);
                        }
                    });
                }
            }
        }
        applyMapInfo(null);
    }

    private void applyMapInfo(TagEntity tag) {
        if (tag == null) {
            imgmap.setBackgroundResource(R.drawable.default_image);
        }
        new Thread(() -> {
            try {
                FutureTarget<File> futureTarget = Glide.with(this).asFile().load(mDataItem.iconUrl).submit();
                File fileSvg = futureTarget.get();
                String contentSvg = FileUtils.getStringFromFilePath(fileSvg.getPath(), null);
                SVG svg = SVG.getFromString(contentSvg);
                if (svg != null) {
                    try {
                        this.svgBase = svg.getBase();
                        // 处理品牌
                        if (this.mMapinfoList != null) {
                            for (MapEntity map : this.mMapinfoList) {
                                if (map.bizType == 0 && !StringUtils.isEmpty(map.mapId)) {
                                    String mapId = map.mapId;
                                    String brandName = map.title == null ? "" : map.title;
                                    String brandNo = map.descrption == null ? "" : map.descrption;
                                    String logo = map.logo == null ? "" : map.logo;
                                    this.svgBase.replaceTextNode(mapId, 1, brandNo);
                                    this.svgBase.replaceTextNode(mapId, 0, brandName);
                                    if (!StringUtils.isEmpty(logo)) {
                                        if (this.svgBase.replaceImageNode(mapId, logo)) {
                                            if (!mHashLogo.containsKey(logo)) {
                                                mHashLogo.put(logo, null);
                                            }
                                        }
                                    }
                                    // 查找品牌在svg的层级
                                    if (!StringUtils.isEmpty(map.bizId)) {
                                        map.nodeLevel = this.svgBase.getNodeLevel(mapId);
                                    }
                                }
                            }
                        }
                        // 处理图片
                        if (mHashLogo != null) {
                            for (String url : mHashLogo.keySet()) {
                                WeakReference<Bitmap> wr = mHashLogo.get(url);
                                if (wr == null) {
                                    Bitmap bitmap = Glide.with(mContext).asBitmap().load(url).submit().get();
                                    mHashLogo.put(url, new WeakReference<>(bitmap));
                                }
                            }
                        }
                        // 处理高亮
                        String svgClass = "";
                        if (tag != null) {
                            if (mMapinfoList != null) {
                                List<String> mapIds = new ArrayList<>();
                                for (MapEntity map : mMapinfoList) {
                                    if (tag.id.equals(map.bizId)) {
                                        mapIds.add(map.mapId);
                                    }
                                }
                                if (mapIds.size() > 0) {
                                    for (String mapId : mapIds) {
                                        List<SVGBase.SvgElement> elements = this.svgBase.getElementsIncludeChildrenById(mapId);
                                        if (elements != null) {
                                            for (int i = 0; i < elements.size(); i++) {
                                                svgClass += "#" + elements.get(i).id + " {fill:red}";
                                                if (i != elements.size() - 1) {
                                                    svgClass += " ";
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        final String svgClassF = svgClass;
                        runOnUiThread(() -> {
                            try {
                                RenderOptions renderOptions = RenderOptions.create().css(svgClassF);
                                Picture picture = svg.renderToPicture(renderOptions);
                                PictureDrawable drawable = pictureDrawableFromPicture(picture);
                                if (tag != null) {
                                    imgmap.updateImageDrawable(drawable);
                                } else {
                                    imgmap.setImageDrawable(drawable);
                                    imgmap.setScale(ContextConstant.IS_LANDSCAPE ? 1.5f : 2.5f);
                                    imgmap.setBackgroundResource(R.color.transparent);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    this.svgBase = null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

    private PictureDrawable pictureDrawableFromPicture(Picture picture) {
        PictureDrawable drawable = new PictureDrawable(picture);
        drawable.setBounds(0, 0, picture.getWidth(), picture.getHeight());
        return drawable;
    }

    public interface IActionCallback {
        void onBrandClicked(String brandId);
    }
}